#pragma once
#include"discovery.hpp"
#include"rpcCaller.hpp"

class RpcClient
{
public:
    using ptr = std::shared_ptr<RpcClient>;
    ~RpcClient() {}

    RpcClient(const Address& registerServer, const std::string serverName = "RpcClient-discovery")
        : _requestor(new Requestor)
        , _caller(new RpcCaller(_requestor))
        , _dispatcher(new Dispatcher)
        , _connPool(new DiscoveryClient(registerServer, serverName, _requestor, _dispatcher))
        {}

    bool connectedRegister(size_t timeOut = 10)
    {
        _connPool->connect();
        while (timeOut--)
        {
            if (_connPool->isCooectedRegister())
            {
                return true;
            }
        }
        return false;
    }

    bool callSync(const std::string& method, const Json::Value& parameters, Json::Value& result)
    {
        auto conn = _connPool->getOneConn(method);
        if (conn == nullptr || !conn->getClientConnection()->connected())
        {
            return false;
        }
        LOG_INFO << "本次选择主机：" << conn->getClientConnection()->perrAddressString();
        _caller->callSync(conn->getClientConnection(), method, parameters, result, conn->getHandlerProtocol());
        return true;
    }

    RpcCallFuture callAsync(const std::string& method, const Json::Value& parameters)
    {
        auto conn = _connPool->getOneConn(method);
        if (conn == nullptr || !conn->getClientConnection()->connected())
        {
            return RpcCallFuture();
        }
        LOG_INFO << "本次选择主机：" << conn->getClientConnection()->perrAddressString();
        return _caller->callAsync(conn->getClientConnection(), method, parameters, conn->getHandlerProtocol());
    }

    bool callBack(const std::string& method, const Json::Value& parameters, RpcCaller::callback cb)
    {
        auto conn = _connPool->getOneConn(method);
        if (conn == nullptr || !conn->getClientConnection()->connected())
        {
            return false;
        }
        LOG_INFO << "本次选择主机：" << conn->getClientConnection()->perrAddressString();
        _caller->callBack(conn->getClientConnection(), method, parameters, cb, conn->getHandlerProtocol());
        return true;
    }

private:
    Requestor::ptr _requestor;
    RpcCaller::ptr _caller;
    Dispatcher::ptr _dispatcher;
    ConnectionPool _connPool;
};